package edu.sjtu.grid.workflow.schedule;

import java.util.List;

import edu.sjtu.grid.workflow.facts.Facts;
import edu.sjtu.grid.workflow.facts.Job;
import edu.sjtu.grid.workflow.facts.Mapping;
import edu.sjtu.grid.workflow.iterator.UpwardRankIterator;

public class HeuristicSearchSchedule_AvgCost extends ScheduleBase{

	private UpwardRankIterator iterator = null;
	private double deadline = 0;
	
	public HeuristicSearchSchedule_AvgCost(Facts facts, double deadline) {
		super(facts, ScheduleType.HeuristicSearch_AvgCost);
		this.deadline = deadline;
		this.getRun().setDeadline(deadline);
	}
	
	public String toString()
	{
		return super.toString("deadline: " + deadline + "\n");
	}
	
	@Override
	protected void doSchedule()
	{
		//upward rank sorting & LFT(latest finished time)
		this.iterator = this.getFacts().getAdag().getUpwardRankIterator();
		
		//search1
		this.setResult(doScheduleHelper1());
		
		//search2
		/*this.currentRun = new Run(this.getFacts(), ScheduleType.HeuristicSearch_AvgCost);
		this.currentRun.setDeadline(deadline);
		doScheduleHelper2();
		if(bestRun != null)
			this.setResult(true, bestRun);
		else
			this.setResult(false);*/
	}
	
	/*private Run bestRun = null;
	private Run currentRun = null;
	
	private void doScheduleHelper2()
	{	
		if(!this.iterator.hasNext())
		{
			currentRun.realRun_AvgCost();
			if(bestRun == null || currentRun.getCost() < bestRun.getCost())
			{
				bestRun = new Run(this.getFacts(), ScheduleType.HeuristicSearch_AvgCost);
				bestRun.setDeadline(deadline);
				for(Mapping map : currentRun.getMappingArray())
					bestRun.confirmMapping(map);
				bestRun.realRun_AvgCost();
			}
			return;
		}
		
		if(this.reachMaxRunTime())
			return;
		
		Job job = (Job)this.iterator.next();
		List<Mapping> mappingList = this.getRun().getMappingList_AvgCost(job, this.deadline);
		for(Mapping map : mappingList)
		{	
			//confirm
			currentRun.confirmMapping(map);
			
			doScheduleHelper2();
			
			//unconfirm
			currentRun.removeMapping(map);
		}
		if(this.iterator.hasBefore())
			this.iterator.before();
		return;
	}*/
	
	private boolean doScheduleHelper1()
	{
		if(this.reachMaxRunTime())
			return false;
		
		if(!this.iterator.hasNext())
			return true;
		
		Job job = (Job)this.iterator.next();
		List<Mapping> mappingList = this.getRun().getMappingList_AvgCost(job, this.deadline);
		for(Mapping map : mappingList)
		{	
			//confirm
			this.getRun().confirmMapping(map);
			
			if(doScheduleHelper1())
				return true;
			
			//unconfirm
			this.getRun().removeMapping(map);
		}
		this.iterator.before();
		return false;
	}

}
